package directory.process;

import generator.service.PropertiesService;
import generator.service.ReadWrite;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringEscapeUtils;

import directory.bean.Field;
import directory.bean.Fields;
import directory.bean.FormDefinition;
import directory.bean.SubFormDefinition;
import directory.utils.DirectoryConstants;


/**
 * Transform Form object into SQL requests and properties files
 * @author jchaline
 * 
 */
public class Generator
{

    private static final Map<String, Integer> entryId;

    static
    {
        Map<String, Integer> aMap = new HashMap<String, Integer>( );
        aMap.put( "text", 6 );
        aMap.put( "textarea", 7 );
        aMap.put( "combo", 5 );
        aMap.put( "radio", 1 );
        aMap.put( "checkbox", 2 );
        aMap.put( "upload", 13 );
        entryId = Collections.unmodifiableMap( aMap );
    }

    /**
     * Private constructor for utility class
     */
    private Generator( )
    {

    }

    /**
     * Generate the files with SQL requets and properties components
     * @param form the form to generate
     * @param propertiesPath the properties file path
     * @param sqlPath the sql file path
     */
    public static void generate( FormDefinition form )
    {
        Integer position = 0;
        String idDirectory = PropertiesService.getProperty( DirectoryConstants.DIRECTORY_ID );
        //id de l'attribut mappé
        String strFirstIdEntry = PropertiesService.getProperty( DirectoryConstants.FIRST_ENTRY_ID );

        //id du champs representant le type d'attribut mappé
        String strFirstIdField = PropertiesService.getProperty( DirectoryConstants.FIRST_FIELD_ID );

        Integer currentIdField = Integer.valueOf( strFirstIdField );
        Integer currentIdEntry = Integer.valueOf( strFirstIdEntry );

        StringBuilder properties = new StringBuilder( );
        StringBuilder sql = new StringBuilder( );

        for ( SubFormDefinition subform : form.getSubforms( ) )
        {
            sql.append( getEntryParentSqllINE( idDirectory, subform.getTitle( ), currentIdEntry, position ) );
            position++;
            currentIdEntry++;
            
            for ( Fields fields : subform.getFields( ) )
            {
                for ( Field field : fields.getFields( ) )
                {
                    properties.append( getFieldPropertyLine( form.getName( ), currentIdEntry, field ) );
                    sql.append( getFieldSqllINE( currentIdField, currentIdEntry, field ) );
                    sql.append( getEntrySqllINE( idDirectory, currentIdField, currentIdEntry, field, position ) );

                    currentIdEntry++;
                    currentIdField++;
                    position++;
                }
            }
        }

        String pathProperties = PropertiesService.getProperty( DirectoryConstants.FILE_PROPERTIES );
        String pathSQL = PropertiesService.getProperty( DirectoryConstants.FILE_SQL );
        generateFile( pathProperties, properties );
        generateFile( pathSQL, sql );

    }

    /**
     * Write into file the content of properties
     * @param pathFile
     * @param StringBuilder
     */
    private static void generateFile( String pathFile, StringBuilder content )
    {
        ReadWrite.write( pathFile, content.toString( ) );
    }

    /**
     * Generate the SQL line for the field
     * @param currentIdField
     * @param currentIdEntry
     * @param field
     * @return
     */
    private static String getFieldSqllINE( Integer currentIdField, Integer currentIdEntry, Field field )
    {
        String sqlRequest = "INSERT INTO directory_field VALUES(" + currentIdField + "," + currentIdEntry
                + ", NULL ,'',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,1);\n";
        return sqlRequest;
    }

    /**
     * Generate the SQL line for the field
     * @param currentIdField
     * @param currentIdEntry
     * @param position
     * @param field
     * @return
     */
    private static String getEntryParentSqllINE( String idDirectory, String subFormTitle, Integer currentIdEntry,
            Integer position )
    {
        String sqlRequest = "INSERT INTO directory_entry VALUES(" + currentIdEntry + ", NULL, " + idDirectory
                + ", 9, '" + StringEscapeUtils.escapeSql( subFormTitle ) + "', '', '', '', 0, 0, 0, 0, 0, 0, 1, 0, "
                + position + ", 0, 0, 0, 0, 0, 1, 0, NULL, 0, NULL, '', 0, 1, 0, NULL); \n";
        return sqlRequest;
    }

    /**
     * Generate the SQL line for the field
     * @param idDirectory
     * @param currentIdField
     * @param currentIdEntry
     * @param field
     * @param position
     * @return
     */
    private static String getEntrySqllINE( String idDirectory, Integer currentIdField, Integer currentIdEntry,
            Field field, Integer position )
    {
        String sqlRequest = "INSERT INTO directory_entry VALUES(" + currentIdEntry + ", NULL, " + idDirectory + ", "
                + getEntryType( field.getType( ) ) + ", '" + StringEscapeUtils.escapeSql( field.getLabel( ) )
                + "', '', '', '', 0, 0, 0, 0, 0, 0, 1, 0, " + position
                + ", 0, 0, 0, 0, 0, 1, 0, NULL, 0, NULL, '', 0, 1, 0, NULL); \n";
        return sqlRequest;
    }

    private static String getFieldPropertyLine( String formName, Integer currentId, Field field )
    {
        String line = "formengine-outputws.form." + formName + ".param.attribute." + field.getName( ) + "=" + currentId
                + "\n";
        return line;
    }

    private static int getEntryType( String strType )
    {
        int typeId = 0;
        if ( entryId.containsKey( strType ) )
        {
            typeId = entryId.get( strType );
        }
        else
        {
            System.err.println( "/!\\ Type inconnu : " + strType + " /!\\ " );
        }
        return typeId;
    }
}
